/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.facebook.common.abilitylistener;

import com.facebook.common.internal.Preconditions;
import ohos.aafwk.ability.Ability;
import ohos.app.AbilityContext;
import ohos.app.Context;

import javax.annotation.Nullable;
import java.lang.ref.WeakReference;

public class AbilityListenerManager {
    /**
     * If given context is an instance of ListenableAbility then creates new instance of
     * WeakReferenceAbilityListenerAdapter and adds it to ability's listeners
     */
    public static void register(AbilityListener abilityListener, Context context) {
        ListenableAbility ability = getListenableAbility(context);
        if (ability != null) {
            Listener listener = new Listener(abilityListener);
            ability.addAbilityListener(listener);
        }
    }

    public static @Nullable
    ListenableAbility getListenableAbility(Context context) {
        if (!(context instanceof ListenableAbility) && context instanceof AbilityContext) {
            context = ((AbilityContext) context).getContext();
        }
        if (context instanceof ListenableAbility) {
            return (ListenableAbility) context;
        }
        return null;
    }

    private static class Listener extends BaseAbilityListener {
        private final WeakReference<AbilityListener> mAbilityListenerRef;

        public Listener(AbilityListener abilityListener) {
            mAbilityListenerRef = new WeakReference<AbilityListener>(abilityListener);
        }

        @Override
        public void onAbilityCreate(Ability ability) {
            AbilityListener abilityVisibilityListener = getListenerOrCleanUp(ability);
            if (abilityVisibilityListener != null) {
                abilityVisibilityListener.onAbilityCreate(ability);
            }
        }

        @Override
        public void onDestroy(Ability ability) {
            AbilityListener abilityVisibilityListener = getListenerOrCleanUp(ability);
            if (abilityVisibilityListener != null) {
                abilityVisibilityListener.onDestroy(ability);
            }
        }

        @Override
        public void onStart(Ability ability) {
            AbilityListener abilityVisibilityListener = getListenerOrCleanUp(ability);
            if (abilityVisibilityListener != null) {
                abilityVisibilityListener.onStart(ability);
            }
        }

        @Override
        public void onStop(Ability ability) {
            AbilityListener abilityVisibilityListener = getListenerOrCleanUp(ability);
            if (abilityVisibilityListener != null) {
                abilityVisibilityListener.onStop(ability);
            }
        }

        @Override
        public void onResume(Ability ability) {
            AbilityListener abilityVisibilityListener = getListenerOrCleanUp(ability);
            if (abilityVisibilityListener != null) {
                abilityVisibilityListener.onResume(ability);
            }
        }

        @Override
        public void onPause(Ability ability) {
            AbilityListener abilityVisibilityListener = getListenerOrCleanUp(ability);
            if (abilityVisibilityListener != null) {
                abilityVisibilityListener.onPause(ability);
            }
        }

        private @Nullable AbilityListener getListenerOrCleanUp(Ability ability) {
            AbilityListener abilityVisibilityListener = mAbilityListenerRef.get();
            if (abilityVisibilityListener == null) {
                Preconditions.checkArgument(ability instanceof ListenableAbility);
                ListenableAbility listenableAbility = (ListenableAbility) ability;
                listenableAbility.removeAbilityListener(this);
            }
            return abilityVisibilityListener;
        }
    }
}
